/***********************************************************************
	filename: 	DaterEventManager.h
	created:	10/4/2012
	author:		4Ys
	
	purpose:	Defines the interface for the EventManager object
*************************************************************************/
#ifndef _DaterEventManager_h_
#define _DaterEventManager_h_

#include "DaterSingleton.h"
#include "DaterEvent.h"
#include "DaterIteratorBase.h"

#include <map>

namespace Dater
{
	struct EventIdentifier
	{
		int user_id;
		int event_id;
		bool operator < (const EventIdentifier& anotherIdentifier) const
		{
			if(user_id < anotherIdentifier.user_id)
				return true;
			else if(user_id == anotherIdentifier.user_id)
			{
				return event_id < anotherIdentifier.event_id;
			}else
				return false;
		}
	};

/*!
\brief
	The EventManager class describes an object that manages creation and lifetime of Event objects.

	The EventManager is the means by which Event objects are created and destroyed.  For each sub-class 
	(if exists) of Event that is to be created, there must exist a EventFactory object which is registered 
	with the EventFactoryManager. Additionally, the EventManager tracks every Event object created, and can
	be used to access those Event objects by name.
*/
	class EventManager : public Singleton <EventManager>
	{
	public:
		/*!
		\brief
			Constructs a new EventManager object.

		\param
			Constructs
		*/
		EventManager();

		/*!
	    \brief
			Destructor for EventManager objects

			This will properly destroy all remaining Event objects.  Note that EventFactory objects will not
			be destroyed (since they are owned by whoever created them).
		*/
		~EventManager(void);

		/*!
		\brief
			Creates a new Event object of the specified type(will be realized later), and gives it the specified unique name.

		\param type
			String that describes the type of Event to be created. A valid EventFactory for the specified type must be registered.

		\param name
			String that holds a unique name that is to be given to the new event. The name cannot be empty.

		\param startTime
			A Time class that stores the start time of the event to be created.

		\param finishTime
			The finish time of the event.

		\param description
			String that the description of the event.
			
		\param userID
			The userID of the user who created this event.

		\return
			Pointer to the newly created Event object.
		*/
		Event* createEvent(const std::string& type, const std::string& name, const Time& startTime, 
			const Time& finishTime, const std::string& description, int userID);

		/*!
		\brief
			Adds an existed Event object of the specified type(will be realized later), and gives it the specified unique name.

		\param type
			String that describes the type of Event to be created. A valid EventFactory for the specified type must be registered.

		\param name
			String that holds a unique name that is to be given to the new event. The name cannot be empty.

		\param startTime
			A Time class that stores the start time of the event to be created.

		\param finishTime
			The finish time of the event.

		\param description
			String that the description of the event.

		\param userID
			The userID of the user who created this event.

		\param eventID
			The eventID of the added event

		\return
			Pointer to the newly added Event object.
		*/
		Event* addEvent(const std::string& type, const std::string& name, const Time& startTime, 
			const Time& finishTime, const Time& createTime, const std::string& description, int userID, int eventID);

		/*!
		\brief
			Destroy the specified Event object.

		\param theEvent
			Pointer to the Event object to be destroyed.  If the event is null, or is not recognised, nothing happens.

		\return
			Nothing
		*/
		void destroyEvent(Event* theEvent);

		/*!
		\brief
			Destroy the specified Event object.

		\param theEvent	
			String containing the name of the Event object to be destroyed.  If an event is not recognised, nothing happens.

		\return
			Nothing.
		*/
		void destroyEvent(EventIdentifier eventIdentifier);

		/*!
		\brief
			Return a pointer to the specified Event object.

		\param name
			String holding the name of the Event object to be returned.

		\return
			Pointer to the Event object with the name.
		*/
		Event* getEvent(EventIdentifier eventIdentifier) const;

		/*!
		\brief
			Examines the list of Event objects to see if one exists with the given name

		\param name
			String holding the name of the Event object to look for.

		\return
			true if an Event object was found with a name matching the name.  
			false if no matching Event object was found.
		*/
		bool isEventPresent(EventIdentifier eventIdentifier) const;

		/*!
		\brief
			Destroys all Window objects within the system

		\return
			Nothing
		*/
		void destroyAllEvents(void);

		/*!
		\brief
			Rename an event.

		\param theEvent
			String holding the current name of the event to be renamed.

		\param new_name
			String holding the new name for the event
		*/
		void renameEvent(EventIdentifier eventIdentifier, const std::string& new_name);

		 /*!
		\brief
			Rename an event.

		\param theEvent
			Pointer to the window to be renamed.

		\param new_name
			String holding the new name for the event
		*/
		void renameEvent(Event* theEvent, const std::string& new_name);

		static void setUidCounter(unsigned long counter);

		static unsigned long getUidCounter();

	private:
		typedef std::map<EventIdentifier, Event*> EventRegistry;	//!< Type used to implement registry of Event objects

		EventRegistry _eventRegistry;	//!< The container that forms the Event registry

		static unsigned long _uid_counter;		//!< Counter used to generate unique event names.

	public:
		typedef ConstBaseIterator< EventRegistry > EventIterator;

		/*!
		\brief
			Return a EventManager::EventIterator object to iterate over the currently defined Events.
		*/
		EventIterator getIterator(void) const;
		
	};

}

#endif